package wating.project;
/*
    等待唤醒机制：多个线程之间的通讯
    案例：生产者和消费者之间的通讯
        创建一个顾客线程任务（消费者），告知老板要的包子数量和种类，wait（）方法进行等待（进入waiting状态 ，无限睡眠，等待唤醒）
                                     被唤醒之后进行吃包子操作
        创建一个老板线程任务（生产者），使用sleep（）方法（休眠一定是时间）花费一定时间去制作包子，包子做好之后，调用notify()方法
                                    唤醒顾客吃包子

    总体思路：java属于抢占调度，所以顾客与老板都会去抢占cpu，若顾客先抢到，则会执行顾客线程任务，进入无线睡眠，从而不再占用cpu
             直到notify（）方法唤醒才可占用cpu；这时不管 老板线程任务是否抢到cpu都会执行老板线程任务，去制作包子

    注意：顾客和老板必须都使用同步代码块包起来，而且必须使用同一个对象锁，保证老板或顾客只有一个在执行
         只有锁对象才可以调用wait（）和notify（）方法，这两个方法都是Object类中的
                                                                 void wait（）：使得线程等待
                                                                 void notify（）：唤醒 单个等待的线程，从而继续直径wait（）方法之后的代码

 */
public class PracticeMain {
    public static void main(String[] args) {
        int number = 20;
        //创建锁对象，保证唯一
        Object obj = new Object();

        //创建顾客线程任务 匿名内部类
        new Thread(){
            @Override
            public void run() {
                while (number>0){
                   synchronized (obj){
                       System.out.println("告知老板所要的包子");
                       //进入睡眠状态
                       try {
                           obj.wait(); //有异常，用try-catch
                       } catch (InterruptedException e) {
                           e.printStackTrace();
                       }
                       System.out.println("这"+number+"个包子真好吃");
                   }
                   System.out.println("======================================");
                }
            }
        }.start(); //启用线程任务

        //创建老板线程任务  匿名内部类
        new Thread(){
            @Override
            public void run() {
                while (number>0){
                    //先休眠才能不会去抢夺对象锁，而让顾客线程先点餐
                    try {
                        //做包子需要的时间
                        Thread.sleep(5000); //sleep()是静态方法，来自Thread类
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                   synchronized (obj){
                       System.out.println("包子做好了");
                       obj.notify(); //唤醒顾客线程任务
                   }
                }
            }
        }.start();
    }
}
